package com.mye.prometheusexportdcim.utils;

import lombok.extern.slf4j.Slf4j;
import org.snmp4j.*;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.*;
import org.snmp4j.security.nonstandard.PrivAES192With3DESKeyExtension;
import org.snmp4j.security.nonstandard.PrivAES256With3DESKeyExtension;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.transport.DefaultUdpTransportMapping;

import java.io.IOException;

/**
 * @author Administrator
 */
@Slf4j
class Snmp4j {


    private Snmp snmp = null;

    private String addr;

    private int version;

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    Snmp4j(String addr, int version) {
        try {
            this.addr = addr;
            this.version = version;
            DefaultUdpTransportMapping transport = new DefaultUdpTransportMapping();
            snmp = new Snmp(transport);
            if (version == SnmpConstants.version3) {
                // 设置安全模式
                USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
                SecurityModels.getInstance().addSecurityModel(usm);
            }
            // 开始监听消息
            transport.listen();
        } catch (IOException e) {
            log.error(LogLocalityUtil.getLogLocality() + "snmp服务发生错误:{} ", e);
        }
    }


    ResponseEvent sendMessage(PDU pdu, String addr, String username, String authWay, String authPassword, String encryptionWay, String encryptionPassword) {
        // 生成目标地址对象
        Address targetAddress = GenericAddress.parse(addr);
        Target target;
        if (version == SnmpConstants.version3) {
            target = convertOfUserTarget(username, authWay, authPassword, encryptionWay, encryptionPassword);
        } else {
            target = convertOfCommunityTarget();
        }
        // 目标对象相关设置
        target.setAddress(targetAddress);
        target.setRetries(1);
        target.setTimeout(1000L);
        // 发送报文 并且接受响应
        try {
            return snmp.send(pdu, target);
        } catch (Exception e) {
            log.error(LogLocalityUtil.getLogLocality() + "从snmp获取数据发送错误:{} ", e);

        }
        return null;
    }

    private Target convertOfCommunityTarget() {
        CommunityTarget target = new CommunityTarget();
        if (version == SnmpConstants.version1) {
            target.setVersion(SnmpConstants.version1);
            target.setCommunity(new OctetString("public"));
        } else {
            target.setVersion(SnmpConstants.version2c);
            target.setCommunity(new OctetString("public"));
        }
        return target;
    }

    private Target convertOfUserTarget(String username, String authWay, String authPassword, String encryptionWay, String encryptionPassword) {


        // 添加用户,
//        UsmUser user = new UsmUser(new OctetString("SHADES"), AuthSHA.ID, new OctetString("SHADESAuthPassword"),
//                PrivDES.ID, new OctetString("SHADESPrivPassword"));
        UsmUser user = new UsmUser(new OctetString(username), getAuth(authWay), new OctetString(authPassword),
                getEncryp(encryptionWay), new OctetString(encryptionPassword));
        snmp.getUSM().addUser(user.getSecurityName(), user);
        Target target = new UserTarget();
        // 设置安全级别
        target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
        target.setSecurityName(new OctetString(username));
        target.setVersion(SnmpConstants.version3);
        return target;
    }


    private OID getEncryp(String encryptionWay) {

        OID ID;
        switch (encryptionWay) {

            case "Priv3DES":
                ID = Priv3DES.ID;
                break;
            case "PrivAES128":
                ID = PrivAES128.ID;
                break;
            case "PrivAES192":
                ID = PrivAES192.ID;
                break;
            case "PrivAES192With3DESKeyExtension":
                ID = PrivAES192With3DESKeyExtension.ID;
                break;
            case "PrivAES256":
                ID = PrivAES256.ID;
                break;
            case "PrivAES256With3DESKeyExtension":
                ID = PrivAES256With3DESKeyExtension.ID;
                break;
            default:
                ID = PrivDES.ID;
                break;

        }

        return ID;
    }

    private OID getAuth(String authWay) {

        OID ID;
        switch (authWay) {
            case "AuthHMAC128SHA224":
                ID = AuthHMAC128SHA224.ID;
                break;
            case "AuthHMAC192SHA256":
                ID = AuthHMAC192SHA256.ID;
                break;
            case "AuthHMAC256SHA384":
                ID = AuthHMAC256SHA384.ID;
                break;
            case "AuthHMAC384SHA512":
                ID = AuthHMAC384SHA512.ID;
                break;
            case "AuthMD5":
                ID = AuthMD5.ID;
                break;
            default:
                ID = AuthSHA.ID;
                break;

        }
        return ID;
    }


}
